Skip to content

UN-3149 [FEAT] Support CSV, TXT, and Excel files in Prompt Studio#1783

Merged
hari-kuriakose merged 7 commits intomainfrom
feature/csv-txt-excel-prompt-studio
Feb 26, 2026
Merged

UN-3149 [FEAT] Support CSV, TXT, and Excel files in Prompt Studio#1783
hari-kuriakose merged 7 commits intomainfrom
feature/csv-txt-excel-prompt-studio

Conversation

@jagadeeswaran-zipstack
Copy link
Contributor

@jagadeeswaran-zipstack jagadeeswaran-zipstack commented Feb 8, 2026

What

Add support for CSV, TXT, and Excel files in Prompt Studio for enterprise users. These file types are stored as-is (no PDF conversion) and displayed in Raw View only.

Why

  • Users need to process structured data files (CSV, Excel) and plain text files in Prompt Studio
  • These file types don't benefit from PDF conversion and should be handled natively
  • Enables extraction from a wider variety of document formats

How

  • Upload flow: Original files always stored in main directory. For convertible types (DOCX, images, PPT), a converted PDF is also stored in converted/ subdirectory for preview
  • CSV/TXT/Excel: Skip PDF conversion entirely, stored as-is in main directory
  • Preview resolution: fetch_contents_ide checks converted/{name}.pdf first for enterprise; falls back to original file
  • Frontend: Auto-switches to Raw View for non-PDF file types; allows direct upload of CSV/TXT/Excel without confirmation modal

Files Changed:

  • backend/prompt_studio/prompt_studio_core_v2/views.py - Upload stores original + converted; fetch resolves converted PDF
  • backend/utils/file_storage/helpers/prompt_studio_file_helper.py - Add converted/ dir, upload_converted_for_ide(), handle CSV/Excel MIME
  • frontend/.../DocumentManager.jsx - Use mimeType for rendering, auto-switch to Raw View
  • frontend/.../ManageDocsModal.jsx - Allow CSV/TXT/Excel in upload validation

Can this PR break any existing features. If yes, please list possible items. If no, please explain why.

No - Changes are enterprise-gated via get_plugin("file_converter"). OSS behavior is unchanged (PDF-only). Existing DOCX/image/PPT uploads now store both original AND converted PDF, maintaining backward compatibility for preview while enabling original file indexing.

Database Migrations

None

Env Config

None

Related Issues or PRs

Notes on Testing

  1. Upload DOCX → Verify file.docx in main dir + converted/file.pdf exists → PDF View shows PDF → Index uses original DOCX
  2. Upload CSV → Verify data.csv in main dir, no converted file → Auto-switches to Raw View → Index uses CSV
  3. Upload TXT → Same as CSV flow
  4. Upload Excel (.xlsx/.xlsm) → Same as CSV flow, shows placeholder message in PDF View
  5. Upload PDF → No change from existing behavior
  6. Delete document → Verify cleanup includes converted/ directory

Checklist

I have read and understood the Contribution Guidelines.

- Store original files in main directory, converted PDFs in converted/ subdir
- CSV/TXT/Excel skip PDF conversion entirely and show only Raw View
- Backend resolves converted PDF transparently for preview (fetch_contents_ide)
- Frontend auto-switches to Raw View for non-PDF file types
- Add upload_converted_for_ide() helper method
- Include converted/ in directory creation and delete cleanup

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 8, 2026

Summary by CodeRabbit

  • New Features

    • Conversion-and-preview flow: non-PDFs can be converted for PDF preview while originals are always preserved.
    • Expanded direct upload support to include PDF, TXT, CSV, and common Excel types for faster uploads.
  • Bug Fixes / UX

    • Auto-switch to Raw View for non-previewable files and clearer preview placeholders.
    • More reliable MIME detection, improved upload/fetch behavior, and strengthened error handling.

Walkthrough

Backend adds converted-PDF preview storage and conversion-aware upload flows; frontend uses MIME type to choose preview vs. Raw View and introduces a direct-upload MIME whitelist for certain file types.

Changes

Cohort / File(s) Summary
Backend prompt studio views
backend/prompt_studio/prompt_studio_core_v2/views.py
fetch_contents_ide will try to serve converted/{name}.pdf for ORIGINAL view when a converter exists (falls back on FileNotFoundError); final GET returns raw contents. upload_for_ide detects MIME with libmagic, may convert non-PDFs to PDF for preview (store under converted/), then stores the original and creates a document record using the original filename.
File storage helper
backend/utils/file_storage/helpers/prompt_studio_file_helper.py
Adds converted/ subdirectory creation and deletion; new upload_converted_for_ide to store converted previews; expands fetch_file_contents to treat text/plain/text/csv as text and return a placeholder for Excel MIME types; cascade delete now removes converted files.
Frontend document preview
frontend/src/components/custom-tools/document-manager/DocumentManager.jsx
Decides rendering by returned mimeType: PDFs use PdfViewer; non-PDF originals clear file URL, set fileData.mimeType and auto-switch to Raw View with a placeholder message. Uses res.data (not res.data.data) and revokes blob URLs on change; improved error handling and logging.
Frontend upload modal
frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx
Adds DIRECT_UPLOAD_TYPES whitelist (PDF, plain text, CSV, common Excel MIME types). Whitelisted MIME types upload immediately; others prompt confirmation.
Frontend output analyzer
frontend/src/components/custom-tools/output-analyzer/OutputAnalyzerCard.jsx
Adjusted base64 payload extraction to res?.data?.data (flattened response), affecting blob creation and object URL generation.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant BackendAPI
    participant Converter
    participant FileStorage
    participant Database

    Client->>BackendAPI: upload_for_ide(file)
    BackendAPI->>BackendAPI: detect MIME (magic), check converter & should_convert_to_pdf
    alt convert to PDF
        BackendAPI->>Converter: convert file -> PDF
        Converter-->>BackendAPI: converted PDF
        BackendAPI->>FileStorage: upload converted PDF to converted/{name}.pdf
        BackendAPI->>FileStorage: store original file in main dir
    else store original
        BackendAPI->>FileStorage: store original file in main dir
    end
    BackendAPI->>Database: create document record (original filename)
    BackendAPI-->>Client: upload response

    Client->>BackendAPI: fetch_contents_ide(file, view=ORIGINAL)
    alt converted PDF exists
        BackendAPI->>FileStorage: fetch converted/{name}.pdf
        FileStorage-->>BackendAPI: converted PDF data
    else fetch original
        BackendAPI->>FileStorage: fetch original file
        FileStorage-->>BackendAPI: original data
    end
    BackendAPI-->>Client: file content response (includes mimeType)

    Client->>Client: render by mimeType (PDF → PdfViewer, non-PDF → placeholder / Raw View)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main feature addition: CSV, TXT, and Excel file support in Prompt Studio.
Description check ✅ Passed The description is comprehensive and well-structured, covering all template sections with detailed information about changes, rationale, implementation approach, testing notes, and compatibility assurances.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/csv-txt-excel-prompt-studio

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx (1)

592-614: ⚠️ Potential issue | 🟡 Minor

Stale error message: "Only PDF files are allowed" is no longer accurate.

When ConfirmMultiDoc is not available and the file type isn't in DIRECT_UPLOAD_TYPES, the error message still says "Only PDF files are allowed" (Line 607). Now that CSV, TXT, and Excel files are also accepted, this message is misleading.

Proposed fix
           if (!ConfirmMultiDoc) {
             setAlertDetails({
               type: "error",
-              content: "Only PDF files are allowed",
+              content: "Only PDF, CSV, TXT, and Excel files are allowed",
             });
           }
backend/utils/file_storage/helpers/prompt_studio_file_helper.py (1)

178-201: ⚠️ Potential issue | 🟠 Major

Verify that text_content_string is always defined before Line 201.

If a file's MIME type is in allowed_content_types but doesn't match any of the explicit branches (PDF, text/plain, text/csv, Excel), execution reaches the else at Line 198, which only logs a warning. Control then falls to Line 201 where text_content_string is referenced — but it was never assigned, causing an UnboundLocalError.

This is a pre-existing issue, but the new branches make it more visible. Consider initializing text_content_string = "" before the if/elif chain or adding a return/raise in the else branch.

Proposed fix
     def fetch_file_contents(
         org_id: str,
         user_id: str,
         tool_id: str,
         file_name: str,
         allowed_content_types: list[str],
     ) -> dict[str, Any]:
         """Method to fetch file contents from the remote location.
         The path is constructed in runtime based on the args
         """
+        text_content_string: str = ""
         fs_instance = EnvHelper.get_storage(
backend/prompt_studio/prompt_studio_core_v2/views.py (1)

576-605: ⚠️ Potential issue | 🟡 Minor

Conversion failure will surface as an unhandled 500 error.

If process_file (Line 581) raises an exception (e.g., corrupted file, unsupported format variant), there's no try/except around the conversion block, so the entire upload request fails with a generic 500. Consider wrapping the conversion in a try/except and either falling back to storing the original without a converted preview, or returning a descriptive error message.

Proposed approach
             if file_converter_service.should_convert_to_pdf(file_type):
+                try:
                     converted_data, converted_name = file_converter_service.process_file(
                         uploaded_file, file_name
                     )
                     PromptStudioFileHelper.upload_converted_for_ide(
                         org_id=UserSessionUtils.get_organization_id(request),
                         user_id=custom_tool.created_by.user_id,
                         tool_id=str(custom_tool.tool_id),
                         file_name=converted_name,
                         file_data=converted_data,
                     )
+                except Exception:
+                    logger.warning(
+                        f"Failed to convert {file_name} to PDF for preview, "
+                        "storing original only"
+                    )
                 # Reset uploaded_file for storing original in main dir
                 uploaded_file.seek(0)
                 file_data = uploaded_file
🤖 Fix all issues with AI agents
In `@backend/prompt_studio/prompt_studio_core_v2/views.py`:
- Line 577: The conversion branch uses the browser-supplied
uploaded_file.content_type (referenced as file_type at the if with
file_converter_plugin) instead of the server-detected MIME from FileValidator,
causing inconsistent behavior; fix by persisting the server-detected MIME (e.g.,
add a property or return value like detected_mime on FileValidator or its
validate() result) or re-run magic.from_buffer() in the view before the
conversion decision, then use that server-detected MIME (detected_mime) in the
conditional (the same place that checks file_converter_plugin and file_type) so
conversion vs direct upload is based on the validated content type.
🧹 Nitpick comments (3)
frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx (1)

593-600: DIRECT_UPLOAD_TYPES is re-created on every beforeUpload call inside the onload callback.

This is a minor allocation concern. Consider hoisting it to module scope as a constant since it never changes.

Proposed refactor

Move it outside the component, near the top of the file:

const DIRECT_UPLOAD_TYPES = new Set([
  "application/pdf",
  "text/plain",
  "text/csv",
  "application/vnd.ms-excel",
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "application/vnd.ms-excel.sheet.macroenabled.12",
]);
backend/utils/file_storage/helpers/prompt_studio_file_helper.py (1)

86-116: upload_converted_for_ide largely duplicates upload_for_ide.

The two methods share the same storage-init and path-resolution logic. Consider extracting a private helper that accepts a subdirectory parameter (e.g., None for main dir, "converted" for the converted subdir) to reduce duplication.

frontend/src/components/custom-tools/document-manager/DocumentManager.jsx (1)

357-370: Consider disabling the "PDF View" tab for non-PDF files instead of showing a placeholder.

Users can still manually switch to the PDF View tab for non-PDF files and see a "preview not available" placeholder. Disabling or hiding the tab would be a cleaner UX, though the current approach is functional.

@jagadeeswaran-zipstack jagadeeswaran-zipstack changed the title [FEAT] Support CSV, TXT, and Excel files in Prompt Studio (Enterprise) UN-3149 [FEAT] Support CSV, TXT, and Excel files in Prompt Studio (Enterprise) Feb 8, 2026
@jagadeeswaran-zipstack jagadeeswaran-zipstack changed the title UN-3149 [FEAT] Support CSV, TXT, and Excel files in Prompt Studio (Enterprise) UN-3149 [FEAT] Support CSV, TXT, and Excel files in Prompt Studio Feb 8, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/components/custom-tools/document-manager/DocumentManager.jsx (1)

155-161: ⚠️ Potential issue | 🟠 Major

Bug: fileData is not reset when switching documents, causing stale mimeType.

When selectedDoc changes, fileUrl and extractTxt are reset but fileData (which holds mimeType) is not. This means between the reset and the new response arriving (or if the new request fails), the previous document's mimeType persists. Since isContentAvailable (line 482-485) and renderDoc (line 358) both depend on fileData.mimeType, stale state can cause incorrect rendering — e.g., showing the non-PDF placeholder for what should be a PDF, or marking content as available when the fetch actually failed.

Proposed fix
  useEffect(() => {
    setFileUrl("");
    setExtractTxt("");
+   setFileData({});
    Object.keys(viewTypes).forEach((item) => {
      handleFetchContent(viewTypes[item]);
    });
  }, [selectedDoc]);

Also reset in handleFetchContent:

  const handleFetchContent = (viewType) => {
    if (viewType === viewTypes.original) {
      setFileUrl("");
      setFileErrMsg("");
+     setFileData({});
    }
🤖 Fix all issues with AI agents
In `@frontend/src/components/custom-tools/document-manager/DocumentManager.jsx`:
- Around line 482-485: The isContentAvailable prop can remain as written but you
must prevent stale fileData from making it true after a failed fetch: update
handleGetDocsError to clear the previous fileData (e.g., reset fileData to
null/empty object) and/or set an explicit fetch-failed flag (e.g.,
fileFetchError) and include that in the isContentAvailable check; specifically,
modify handleGetDocsError to reset the state that holds the prior mimeType
(refer to fileData and handleGetDocsError) so that isContentAvailable (which
depends on fileUrl and fileData.mimeType) cannot be true after a fetch failure.
- Around line 259-261: The FileReader.onerror handler currently throws an
exception inside the async callback (reader.onerror) which becomes unhandled;
instead, update the component's error state inside that callback (e.g., call
your state setter such as setError or setFileError with a descriptive message
and the event/error details) and avoid throwing — locate reader.onerror in
DocumentManager.jsx and replace the throw new Error("Fail to load the file")
with a call that sets the component error state and optionally logs the event so
the UI can render the error.
🧹 Nitpick comments (1)
frontend/src/components/custom-tools/document-manager/DocumentManager.jsx (1)

356-370: Unused docName parameter in renderDoc.

After the refactor to mimeType-based rendering, docName is no longer used inside renderDoc. Consider removing it to avoid confusion.

Proposed cleanup
-  const renderDoc = (docName, fileUrl, highlightData) => {
+  const renderDoc = (fileUrl, highlightData) => {

And update the call site at line 489:

-          {renderDoc(selectedDoc?.document_name, blobFileUrl, highlightData)}
+          {renderDoc(blobFileUrl, highlightData)}

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx (2)

610-615: ⚠️ Potential issue | 🟡 Minor

Update error message to reflect all allowed file types.

The error message "Only PDF files are allowed" is now inaccurate since CSV, TXT, and Excel files can also be uploaded directly. This will confuse users who attempt to upload unsupported formats.

📝 Proposed fix
           if (!ConfirmMultiDoc) {
             setAlertDetails({
               type: "error",
-              content: "Only PDF files are allowed",
+              content: "Only PDF, CSV, TXT, and Excel files are allowed",
             });
           }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx`
around lines 610 - 615, The error message in ManageDocsModal.jsx currently set
when ConfirmMultiDoc is false is inaccurate; update the setAlertDetails call
(inside the ConfirmMultiDoc check) to use an accurate message listing the
allowed types (e.g., "Only PDF, CSV, TXT, and Excel files are allowed") or a
clear generic message like "Unsupported file type; allowed: PDF, CSV, TXT,
Excel" so users see the correct allowed formats; ensure you update the string
passed to setAlertDetails({ type: "error", content: ... }) where ConfirmMultiDoc
is evaluated.

608-621: ⚠️ Potential issue | 🔴 Critical

Backend serializer will reject CSV, TXT, and Excel uploads in OSS mode.

The frontend allows CSV, TXT, and Excel uploads via DIRECT_UPLOAD_TYPES, but the backend's FileUploadIdeSerializer validates against FileKey.FILE_UPLOAD_ALLOWED_EXT and FileKey.FILE_UPLOAD_ALLOWED_MIME. In OSS mode (without the file_converter plugin), these default to ["pdf"] and ["application/pdf"] respectively. Users will receive a serializer validation error when attempting these uploads, creating a mismatch between frontend allowlist and backend validation. The file_converter plugin gating only affects file conversion logic, not the initial upload validation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx`
around lines 608 - 621, Frontend permits CSV/TXT/Excel via DIRECT_UPLOAD_TYPES
but backend FileUploadIdeSerializer enforces
FileKey.FILE_UPLOAD_ALLOWED_EXT/MIME (OSS defaults to pdf), causing validation
failures; update the upload decision flow in ManageDocsModal.jsx to consult the
backend-supported upload types or the file_converter availability before
treating a file as "direct": either fetch allowed extensions/mimes from the
server (or read a passed-in prop/feature flag like isFileConverterEnabled) and
use that to compute DIRECT_UPLOAD_TYPES, or fall back to only allowing PDF as
direct upload; adjust the branch around DIRECT_UPLOAD_TYPES, setFileToUpload,
and resolve(file) so non-supported types show the ConfirmMultiDoc/error path
instead of resolving immediately.
🧹 Nitpick comments (1)
frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx (1)

598-606: Move DIRECT_UPLOAD_TYPES to module scope.

The Set is recreated on every file upload since it's defined inside the reader.onload callback. Define it once at the top of the file as a module-level constant for better clarity and minor efficiency.

✨ Suggested refactor

Add near the top of the file (e.g., after the imports or near line 67 with indexTypes):

const DIRECT_UPLOAD_TYPES = new Set([
  "application/pdf",
  "text/plain",
  "text/csv",
  "application/vnd.ms-excel",
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  "application/vnd.ms-excel.sheet.macroenabled.12",
]);

Then remove lines 598-606 from inside reader.onload.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx`
around lines 598 - 606, The DIRECT_UPLOAD_TYPES Set is currently created inside
the reader.onload callback causing it to be recreated on every upload; move the
constant to module scope by declaring DIRECT_UPLOAD_TYPES once near the top of
ManageDocsModal.jsx (e.g., after imports or near the existing indexTypes
constant) and remove the inline declaration inside the reader.onload handler so
the reader.onload code references the module-level DIRECT_UPLOAD_TYPES instead.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx`:
- Around line 610-615: The error message in ManageDocsModal.jsx currently set
when ConfirmMultiDoc is false is inaccurate; update the setAlertDetails call
(inside the ConfirmMultiDoc check) to use an accurate message listing the
allowed types (e.g., "Only PDF, CSV, TXT, and Excel files are allowed") or a
clear generic message like "Unsupported file type; allowed: PDF, CSV, TXT,
Excel" so users see the correct allowed formats; ensure you update the string
passed to setAlertDetails({ type: "error", content: ... }) where ConfirmMultiDoc
is evaluated.
- Around line 608-621: Frontend permits CSV/TXT/Excel via DIRECT_UPLOAD_TYPES
but backend FileUploadIdeSerializer enforces
FileKey.FILE_UPLOAD_ALLOWED_EXT/MIME (OSS defaults to pdf), causing validation
failures; update the upload decision flow in ManageDocsModal.jsx to consult the
backend-supported upload types or the file_converter availability before
treating a file as "direct": either fetch allowed extensions/mimes from the
server (or read a passed-in prop/feature flag like isFileConverterEnabled) and
use that to compute DIRECT_UPLOAD_TYPES, or fall back to only allowing PDF as
direct upload; adjust the branch around DIRECT_UPLOAD_TYPES, setFileToUpload,
and resolve(file) so non-supported types show the ConfirmMultiDoc/error path
instead of resolving immediately.

---

Nitpick comments:
In `@frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx`:
- Around line 598-606: The DIRECT_UPLOAD_TYPES Set is currently created inside
the reader.onload callback causing it to be recreated on every upload; move the
constant to module scope by declaring DIRECT_UPLOAD_TYPES once near the top of
ManageDocsModal.jsx (e.g., after imports or near the existing indexTypes
constant) and remove the inline declaration inside the reader.onload handler so
the reader.onload code references the module-level DIRECT_UPLOAD_TYPES instead.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between c4fe4e2 and d757091.

📒 Files selected for processing (4)
  • backend/prompt_studio/prompt_studio_core_v2/views.py
  • frontend/src/components/custom-tools/document-manager/DocumentManager.jsx
  • frontend/src/components/custom-tools/manage-docs-modal/ManageDocsModal.jsx
  • frontend/src/components/custom-tools/output-analyzer/OutputAnalyzerCard.jsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • backend/prompt_studio/prompt_studio_core_v2/views.py
  • frontend/src/components/custom-tools/document-manager/DocumentManager.jsx

hari-kuriakose and others added 2 commits February 26, 2026 16:56
…viewer

- Use magic.from_buffer() for server-side MIME detection instead of
  browser-supplied content_type during file upload
- Replace unhandled throw in FileReader.onerror with setFileErrMsg
- Clear fileData state on fetch errors to prevent stale isContentAvailable

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
frontend/src/components/custom-tools/document-manager/DocumentManager.jsx (1)

119-119: Remove temporary console logging from document fetch/render paths.

These logs add noise and may expose document metadata in production browsers.

Suggested cleanup
-    console.log("here--->", fileData);
@@
-    console.log(selectedDoc);
@@
-    console.log("response-->", viewType, mimeType);
@@
-        console.log("blob-->", blob);
@@
-    console.log(fileData);

Also applies to: 167-167, 255-255, 261-261, 370-370

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/components/custom-tools/document-manager/DocumentManager.jsx` at
line 119, Remove the temporary console.log calls that expose document data
(e.g., the console.log("here--->", fileData) and other console.log usages noted
around the fetch/render paths) in DocumentManager.jsx; locate the log statements
that print fileData and any similar debug output and delete them (or replace
with a guarded debug logger that only runs in non-production) so no document
metadata is emitted to the browser console during normal operation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@frontend/src/components/custom-tools/document-manager/DocumentManager.jsx`:
- Line 119: Remove the temporary console.log calls that expose document data
(e.g., the console.log("here--->", fileData) and other console.log usages noted
around the fetch/render paths) in DocumentManager.jsx; locate the log statements
that print fileData and any similar debug output and delete them (or replace
with a guarded debug logger that only runs in non-production) so no document
metadata is emitted to the browser console during normal operation.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between d757091 and e5dd536.

📒 Files selected for processing (2)
  • backend/prompt_studio/prompt_studio_core_v2/views.py
  • frontend/src/components/custom-tools/document-manager/DocumentManager.jsx

@github-actions
Copy link
Contributor

Frontend Lint Report (Biome)

All checks passed! No linting or formatting issues found.

@sonarqubecloud
Copy link

@github-actions
Copy link
Contributor

Test Results

Summary
  • Runner Tests: 11 passed, 0 failed (11 total)
  • SDK1 Tests: 63 passed, 0 failed (63 total)

Runner Tests - Full Report
filepath function $$\textcolor{#23d18b}{\tt{passed}}$$ SUBTOTAL
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_logs}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_cleanup}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_cleanup\_skip}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_client\_init}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_get\_image\_exists}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_get\_image}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_get\_container\_run\_config}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_get\_container\_run\_config\_without\_mount}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_run\_container}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_get\_image\_for\_sidecar}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{runner/src/unstract/runner/clients/test\_docker.py}}$$ $$\textcolor{#23d18b}{\tt{test\_sidecar\_container}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{TOTAL}}$$ $$\textcolor{#23d18b}{\tt{11}}$$ $$\textcolor{#23d18b}{\tt{11}}$$
SDK1 Tests - Full Report
filepath function $$\textcolor{#23d18b}{\tt{passed}}$$ SUBTOTAL
$$\textcolor{#23d18b}{\tt{tests/test\_platform.py}}$$ $$\textcolor{#23d18b}{\tt{TestPlatformHelperRetry.test\_success\_on\_first\_attempt}}$$ $$\textcolor{#23d18b}{\tt{2}}$$ $$\textcolor{#23d18b}{\tt{2}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_platform.py}}$$ $$\textcolor{#23d18b}{\tt{TestPlatformHelperRetry.test\_retry\_on\_connection\_error}}$$ $$\textcolor{#23d18b}{\tt{2}}$$ $$\textcolor{#23d18b}{\tt{2}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_platform.py}}$$ $$\textcolor{#23d18b}{\tt{TestPlatformHelperRetry.test\_non\_retryable\_http\_error}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_platform.py}}$$ $$\textcolor{#23d18b}{\tt{TestPlatformHelperRetry.test\_retryable\_http\_errors}}$$ $$\textcolor{#23d18b}{\tt{3}}$$ $$\textcolor{#23d18b}{\tt{3}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_platform.py}}$$ $$\textcolor{#23d18b}{\tt{TestPlatformHelperRetry.test\_post\_method\_retry}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_platform.py}}$$ $$\textcolor{#23d18b}{\tt{TestPlatformHelperRetry.test\_retry\_logging}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_prompt.py}}$$ $$\textcolor{#23d18b}{\tt{TestPromptToolRetry.test\_success\_on\_first\_attempt}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_prompt.py}}$$ $$\textcolor{#23d18b}{\tt{TestPromptToolRetry.test\_retry\_on\_errors}}$$ $$\textcolor{#23d18b}{\tt{2}}$$ $$\textcolor{#23d18b}{\tt{2}}$$
$$\textcolor{#23d18b}{\tt{tests/test\_prompt.py}}$$ $$\textcolor{#23d18b}{\tt{TestPromptToolRetry.test\_wrapper\_methods\_retry}}$$ $$\textcolor{#23d18b}{\tt{4}}$$ $$\textcolor{#23d18b}{\tt{4}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_connection\_error\_is\_retryable}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_timeout\_is\_retryable}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_http\_error\_retryable\_status\_codes}}$$ $$\textcolor{#23d18b}{\tt{3}}$$ $$\textcolor{#23d18b}{\tt{3}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_http\_error\_non\_retryable\_status\_codes}}$$ $$\textcolor{#23d18b}{\tt{5}}$$ $$\textcolor{#23d18b}{\tt{5}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_http\_error\_without\_response}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_os\_error\_retryable\_errno}}$$ $$\textcolor{#23d18b}{\tt{5}}$$ $$\textcolor{#23d18b}{\tt{5}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_os\_error\_non\_retryable\_errno}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestIsRetryableError.test\_other\_exception\_not\_retryable}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCalculateDelay.test\_exponential\_backoff\_without\_jitter}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCalculateDelay.test\_exponential\_backoff\_with\_jitter}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCalculateDelay.test\_max\_delay\_cap}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCalculateDelay.test\_max\_delay\_cap\_with\_jitter}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryWithExponentialBackoff.test\_successful\_call\_first\_attempt}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryWithExponentialBackoff.test\_retry\_after\_transient\_failure}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryWithExponentialBackoff.test\_max\_retries\_exceeded}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryWithExponentialBackoff.test\_retry\_with\_custom\_predicate}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryWithExponentialBackoff.test\_no\_retry\_with\_predicate\_false}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryWithExponentialBackoff.test\_exception\_not\_in\_tuple\_not\_retried}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_default\_configuration}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_environment\_variable\_configuration}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_invalid\_max\_retries}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_invalid\_base\_delay}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_invalid\_multiplier}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_jitter\_values}}$$ $$\textcolor{#23d18b}{\tt{2}}$$ $$\textcolor{#23d18b}{\tt{2}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_custom\_exceptions\_only}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_custom\_predicate\_only}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_both\_exceptions\_and\_predicate}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestCreateRetryDecorator.test\_exceptions\_match\_but\_predicate\_false}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestPreconfiguredDecorators.test\_retry\_platform\_service\_call\_exists}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestPreconfiguredDecorators.test\_retry\_prompt\_service\_call\_exists}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestPreconfiguredDecorators.test\_platform\_service\_decorator\_retries\_on\_connection\_error}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestPreconfiguredDecorators.test\_prompt\_service\_decorator\_retries\_on\_timeout}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryLogging.test\_warning\_logged\_on\_retry}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryLogging.test\_info\_logged\_on\_success\_after\_retry}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{tests/utils/test\_retry\_utils.py}}$$ $$\textcolor{#23d18b}{\tt{TestRetryLogging.test\_exception\_logged\_on\_giving\_up}}$$ $$\textcolor{#23d18b}{\tt{1}}$$ $$\textcolor{#23d18b}{\tt{1}}$$
$$\textcolor{#23d18b}{\tt{TOTAL}}$$ $$\textcolor{#23d18b}{\tt{63}}$$ $$\textcolor{#23d18b}{\tt{63}}$$

@hari-kuriakose hari-kuriakose merged commit a6e1886 into main Feb 26, 2026
7 checks passed
@hari-kuriakose hari-kuriakose deleted the feature/csv-txt-excel-prompt-studio branch February 26, 2026 15:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants